package com.h117121.fashionshop.controller.admin;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import com.h117121.fashionshop.constant.AppConstant;
import com.h117121.fashionshop.controller.generic.GenericController;
import com.h117121.fashionshop.core.dom.Producer;
import com.h117121.fashionshop.core.dom.Product;
import com.h117121.fashionshop.core.dom.ProductQuery;
import com.h117121.fashionshop.core.dom.ProductType;
import com.h117121.fashionshop.core.dom.ResultPage;
import com.h117121.fashionshop.core.exception.EntityNotFoundException;
import com.h117121.fashionshop.customeditor.BaseDomCustomEditor;
import com.h117121.fashionshop.validator.UpdateProductValidator;

@Controller
@RequestMapping("/admin/product")
public class AdminProductController extends GenericController {
	@Autowired
	private MessageSource messageSource;

	@Autowired
	private UpdateProductValidator validator;

	@InitBinder
	protected void initBinder(WebDataBinder binder) {
		SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
		binder.registerCustomEditor(Date.class, new CustomDateEditor(
				dateFormat, true));
		binder.registerCustomEditor(
				Producer.class,
				new BaseDomCustomEditor<Producer>(businessService
						.getAllProducer()));
		binder.registerCustomEditor(
				ProductType.class,
				new BaseDomCustomEditor<ProductType>(businessService
						.getAllProductType()));
	}

	@RequestMapping(method = RequestMethod.GET)
	protected String showPage(HttpServletRequest request,
			@ModelAttribute(value = "query") ProductQuery query,
			@RequestParam(value = "page", required = false) String page) {
		int indexPage = 0;
		if (page != null && !page.isEmpty()) {
			try {
				indexPage = Integer.parseInt(page);
				indexPage -= 1;
				if (indexPage < 0)
					indexPage = 0;
			} catch (NumberFormatException e) {
				indexPage = 0;
			}
		}

		if (query.getKeyWord() != null && !query.getKeyWord().isEmpty()) {
			try {
				Product product = businessService.getProduct(Long
						.parseLong(query.getKeyWord()));
				ResultPage rs = new ResultPage();
				rs.setNumItems(1);
				rs.setNumPage(1);
				rs.setCurrentPage(1);
				List<Product> container = new ArrayList<Product>();
				container.add(product);
				rs.setResult(container);
			} catch (NumberFormatException e) {
				request.setAttribute("resultPage", businessService
						.findProductByKeyword(query.getKeyWord(), indexPage,
								AppConstant.ADMIN_NUM_ITEM_PER_PAGE));
			} catch (EntityNotFoundException e) {
				request.setAttribute("resultPage", businessService
						.findProductByKeyword(query.getKeyWord(), indexPage,
								AppConstant.ADMIN_NUM_ITEM_PER_PAGE));
			}

			String paraURL = ((HttpServletRequest) request).getQueryString();
			if (paraURL.contains("&page=")) {
				request.setAttribute("pageURL",
						paraURL.substring(0, paraURL.indexOf("&page=")));
			} else {
				request.setAttribute("pageURL", paraURL);
			}
		} else {
			request.setAttribute("resultPage", businessService.getAllProduct(
					indexPage, AppConstant.ADMIN_NUM_ITEM_PER_PAGE));
		}

		return "AdminProductPage";
	}

	@RequestMapping(value = "/edit", method = RequestMethod.GET)
	protected String showEditProduct(
			@RequestParam(value = "pid", required = false) String id,
			ModelMap model) {
		if (id != null) {
			try {
				model.addAttribute("product",
						businessService.getProduct(Long.parseLong(id)));
			} catch (EntityNotFoundException e) {
				model.addAttribute("notfound", true);
			}
		} else {
			model.addAttribute("product", new Product());
		}
		return "AdminProductDetailPage";
	}

	@RequestMapping(value = "/edit", method = RequestMethod.POST)
	protected String editProduct(HttpServletRequest request,
			@RequestParam(value = "pid", required = false) String id,
			@ModelAttribute(value = "product") Product product,
			BindingResult errors, ModelMap model) {
		validator.validate(product, errors);
		if (errors.hasErrors()) {
			return "AdminProductDetailPage";
		}

		if (id == null) {
			product.setDateAdded(new Date());
			try {
				businessService.updateProduct(product);
			} catch (EntityNotFoundException e) {
				errors.reject("notfound.product");
				return "AdminProductDetailPage";
			}
		}

		product.setImagePath("/images/products/" + product.getId() + ".jpg");
		try {
			businessService.updateProduct(product);
		} catch (EntityNotFoundException e1) {
			errors.reject("notfound.product");
			return "AdminProductDetailPage";
		}

		MultipartFile file = product.getImage();

		if (null != file && file.getSize() != 0) {
			String path = request.getSession().getServletContext()
					.getRealPath("/");
			path += "/images/products/" + product.getId() + ".jpg";
			System.out.println(path);
			try {
				InputStream inputStream = file.getInputStream();
				OutputStream outputStream = new FileOutputStream(path);
				int readBytes = 0;
				byte[] buffer = new byte[10000];
				while ((readBytes = inputStream.read(buffer, 0, 10000)) != -1) {
					outputStream.write(buffer, 0, readBytes);
				}
				outputStream.close();

			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		model.addAttribute("successfulMessage", true);
		return "AdminProductDetailPage";
	}

	@RequestMapping(value = "/delete", method = RequestMethod.GET)
	protected String deleteProduct(HttpServletRequest request,
			@RequestParam(value = "pid", required = true) String id) {
		Product product = null;
		String referer = request.getHeader("Referer");
		String queryString = "";

		try {
			product = businessService.getProduct(Long.parseLong(id));
			businessService.deleteProduct(product);
			request.setAttribute("successfulMessage", true);
		} catch (EntityNotFoundException e) {
			request.setAttribute("notfound", true);
		}

		if (referer != null) {
			if (referer.contains("?")) {
				queryString = referer.substring(referer.indexOf("?"));
			}
		}
		return "forward:/admin/product" + queryString;
	}

	@ModelAttribute("productTypes")
	public Map<String, String> populateProductTypesList(Locale locale) {
		Map<String, String> productTypes = new LinkedHashMap<String, String>();
		List<ProductType> list = businessService.getAllProductType();

		productTypes.put(null, messageSource.getMessage(
				"message.choose_a_product_type", null, locale));
		for (ProductType productType : list) {
			productTypes.put("" + productType.getId(), productType.getName());
		}
		return productTypes;
	}

	@ModelAttribute("producers")
	public Map<String, String> populateProducersList(Locale locale) {
		Map<String, String> producers = new LinkedHashMap<String, String>();
		List<Producer> list = businessService.getAllProducer();

		producers.put(null, messageSource.getMessage(
				"message.choose_a_producer", null, locale));
		for (Producer producer : list) {
			producers.put("" + producer.getId(), producer.getName());
		}
		return producers;
	}
}
